### Upsert envelope details

Specifying `ENVELOPE UPSERT` creates a source that supports Kafka's standard
key-value convention, and supports inserts, updates, and deletes within
Materialize. The source is also compatible with Kafka's log-compaction feature.

#### Inserts, updates, deletes

When Materialize receives a message, it checks the message's key and offset.

- If Materialize does not contain a record with a matching key, it inserts the
  message's payload.
- If the key matches another record with an earlier offset, Materialize updates
  the record with the message's payload.

    - If the payload is _null_, Materialize deletes the record.

#### Key columns

- Sources with the upsert envelope also decode a message's key, and let you
  interact with it like the source's other columns. These columns are placed
  before the decoded payload columns in the source.
    - If the format of the key is either plain text or raw bytes, the key is
      treated as single column. The default key column name is `key0`.
    - If the key format is Avro, its field names will be converted to column
      names, and they're placed before the decoded payload columns.

    Note that the diagrams on this page do not detail using text- or
    byte-formatted keys with Avro-formatted payloads. However, you can integrate
    both of these features using the `format_spec`s outlined in [`CREATE SOURCE`:
    Avro over Kafka](../avro-kafka/#format_spec) and [`CREATE SOURCE`:
    Text or bytes over Kafka](../text-kafka/#syntax).
- By default, the key is decoded using the same format as the payload. However,
  you can explicitly set the key's format using **UPSERT FORMAT...**.
- If you are using the Confluent Schema Registry, Materialize looks for the key
  and payload schemas using the
  [`TopicNameStrategy`](https://docs.confluent.io/current/schema-registry/serdes-develop/index.html).
